#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <cstring>
#include <time.h>
#include <malloc.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#define TAG "Abbott"

#ifdef NO_LOG
#define LOG_E(fmt, ...)
#define LOG_W(fmt, ...)
#define LOG_I(fmt, ...)
#define LOG_D(fmt, ...)
#else
// 红色
#define LOG_E(fmt, ...)                                               \
    printf("\033[1m\033[40;31m [E][" TAG "](%s|%d)" fmt " \033[0m\n", \
           __func__, __LINE__, ##__VA_ARGS__)
// 黄色
#define LOG_W(fmt, ...)                                               \
    printf("\033[1m\033[40;33m [W][" TAG "](%s|%d)" fmt " \033[0m\n", \
           __func__, __LINE__, ##__VA_ARGS__)
// 白色
#define LOG_I(fmt, ...)                                               \
    printf("\033[1m\033[40;37m [I][" TAG "](%s|%d)" fmt " \033[0m\n", \
           __func__, __LINE__, ##__VA_ARGS__)
// 深绿色
#define LOG_D(fmt, ...)                                               \
    printf("\033[1m\033[40;36m [D][" TAG "](%s|%d)" fmt " \033[0m\n", \
           __func__, __LINE__, ##__VA_ARGS__)
#endif

enum YuvFormat
{
    // Planar，三个分量分开存放
    // Semi-Planar，Y分量单独存放，UV分量交错一起存放
    // Packed/Interleaved，三个分量交错一起存放

    // ********************                 420 Planar              ********************
    // YYYY
    // YYYY
    // UU
    // VV
    I420 = 0, // YU12

    // YYYY
    // YYYY
    // VV
    // UU
    YV12,
    // ********************                 420 Planar              ********************

    // ********************                 420 Semi-planar         ********************
    // YYYY
    // YYYY
    // UVUV
    NV12,

    // YYYY
    // YYYY
    // VUVU
    NV21,
    //  ********************                420 Semi-planar         ********************

    //  ********************                422 Planar              ********************
    // YYYY
    // YYYY
    // UUUU
    // VVVV
    I422 = 100,

    // YYYY
    // YYYY
    // VVVV
    // UUUU
    YV16,
    //  ********************                422 Planar              ********************

    //  ********************                422 Semi-planar         ********************
    // YYYY
    // YYYY
    // VUVU
    // VUVU
    NV61,

    // YYYY
    // YYYY
    // UVUV
    // UVUV
    NV16,
    //  ********************                422 Semi-planar         ********************

    //  ********************                422 Interleaved         ********************
    // YUVY YUVY
    // YUVY YUVY
    YUYV,

    // VYUY VYUY
    // VYUY VYUY
    VYUY,

    // UYVY UYVY
    // UYVY UYVY
    UYVY,

    //  ********************                422 Interleaved         ********************

    //  ********************                444 Planar              ********************
    // YYYY
    // YYYY
    // UUUU
    // UUUU
    // VVVV
    // VVVV
    I444 = 200,

    // YYYY
    // YYYY
    // VVVV
    // VVVV
    // UUUU
    // UUUU
    YV24,
    //  ********************                444 Planar              ********************

    // ********************                 444 Semi-planar         ********************
    // YYYY
    // YYYY
    // UVUVUVUV
    // UVUVUVUV
    NV24,

    // YYYY
    // YYYY
    // VUVUVUVU
    // VUVUVUVU
    NV42,
    // ********************                 444 Semi-planar         ********************

    // ********************                 444 Packed              ********************
    // YUV YUV
    // YUV YUV
    YUV444,
    // ********************                 444 Packed              ********************

    RGB = 300
};

// convert
void convertUYVYtoI420(char *pSrcImage, char *pDstImage, int width, int height);
void convertUYVYtoNV21(char *pSrcImage, char *pDstImage, int width, int height);
void convertUYVYtoNV12(char *pSrcImage, char *pDstImage, int width, int height);
void convertNV21ToNV12(char *pSrcImage, char *pDstImage, int width, int height);
// yyyyy     yyyy        yyyy         yyyy
// uvuv      uvuv        uvuv        uvuv
// TO
// yyyy
// yyyy
// yyyy
// yyyy
// uvuv
// uvuv
// uvuv
// uvuv
void merge4NV12To1NV12(char *src1, char *src2, char *src3, char *src4, char *dst, int srcWidth, int srcHeight);
// yyyy
// yyyy
// yyyy
// yyyy
// uvuv
// uvuv
// uvuv
// uvuv
// TO
// yyyyy     yyyy        yyyy         yyyy
// uvuv      uvuv        uvuv        uvuv
void split4NV12To4NV12SideBySide(char *src, char *dst, int srcWidth, int srcHeight);
void merge4UYVYTo1UYVY(char *src1, char *src2, char *src3, char *src4, char *dst, int srcWidth, int srcHeight);

// draw YUV
void drawNV12Rectangle(char *image, int nv12_width, int nv12_height, int left, int right, int top, int bottom);
void drawUYVYRectangle(char *image, int uyvy_width, int uyvy_height, int left, int right, int top, int bottom);

// 获得时间，单位毫秒
int64_t get_milliseconds();

//  Load YUV Save Yuv
int LoadImg(const char *inputFile, char *data, int size);
const char *yuvFormatToString(YuvFormat format);
int yuvImageSize(int width, int height, YuvFormat format);
int saveYUV(char *data, int width, int height, YuvFormat format);

// c pthread
void testPthread();

// c input output
void testPutchar();
void testGetchar();
void testPrintf();
void testScanf();
void testFgets();
void testSprintf();
void testSnprintf();
void testSscanf();

// c string

//字符串反转
void reverseString(char *src);

